package com.sjb.sixteen_journey_backend.interceptors;

import com.sjb.sixteen_journey_backend.common.JwtProperties;
import com.sjb.sixteen_journey_backend.common.NotRequiringLoginUrlsProperties;
import com.sjb.sixteen_journey_backend.handler.exception.CustomException;
import com.sjb.sixteen_journey_backend.handler.exception.CustomExceptionCodeMsg;
import com.sjb.sixteen_journey_backend.utils.JwtUtil;
import com.sjb.sixteen_journey_backend.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Arrays;
import java.util.Map;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private NotRequiringLoginUrlsProperties notRequiringLoginUrls;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();

        //验证token
        try {
            // 获取到JWT的Token
            String token = request.getHeader(jwtProperties.getTokenHeader());
            if (token != null) {
                Map<String, Object> claims = JwtUtil.parseToken(token);
                //往redis中存储一个人键值对 从redis中获取相同的token
                ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
                String redisToken = operations.get(token);
                log.info("redisToken:" + redisToken);
                if (redisToken.isEmpty()) {
                    //token已经失效了
                    throw new CustomException(CustomExceptionCodeMsg.REDIS_KEY_NOT_FOUND);
                }

//           把业务数据存储到ThreadLocal中
                claims.put("token", token);
                ThreadLocalUtil.set(claims);

                //放行
                return true;
            } else {
                if (Arrays.stream(notRequiringLoginUrls.getUrl()).anyMatch(u -> url.indexOf(u) >= 0)) {
                    //继续往下交给其他烂截器或者请求处理方法处理
                    return true;
                }
            }

        } catch (Exception e) {
            log.info(e.getMessage());
            throw new CustomException(CustomExceptionCodeMsg.UNABLE_TO_CONNECT_TO_REDIS);
        }

        return false;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清空ThreadLocal中的数据
        ThreadLocalUtil.remove();
    }

}
